Laravel / Steps / jwt token integration
JWT Token integration
-
STEP
1. Enable API routes in Laravel 11:
php artisan install:api 2.Update the API middleware to throw an exception instead of redirecting to login for authentication exceptions:
bootstrap/app.php
use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Auth\AuthenticationException; use Illuminate\Http\Request; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { // }) ->withExceptions(function (Exceptions $exceptions) { $exceptions->render(function (AuthenticationException $e, Request $request) { if ($request->is('api/*')) { return response()->json([ 'message' => $e->getMessage(), ], 401); } }); })->create(); 3.Run the following command to install the latest version of the JWT Auth package:
composer require tymon/jwt-auth 4. Publish the package config file:
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider" 5. Generate a secret key. This will add JWT config values on .env file:
php artisan jwt:secret 6. Update auth guard config:
config/auth.php
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ], 7. In the User model, implement the Tymon\JWTAuth\Contracts\JWTSubject contract and add the getJWTIdentifier() and getJWTCustomClaims() methods:
app/Models/User.php
namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Tymon\JWTAuth\Contracts\JWTSubject; class User extends Authenticatable implements JWTSubject { use HasFactory, Notifiable; protected $fillable = [ 'name', 'email', 'password', ]; protected $hidden = [ 'password', 'remember_token', ]; protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; } public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; } } 8. Create the AuthController
php artisan make:controller AuthController 9. app/Http/Controllers/AuthController.php
namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Models\User; use Illuminate\Support\Facades\Validator; use Tymon\JWTAuth\Facades\JWTAuth; class AuthController extends Controller { public function register() { $validator = Validator::make(request()->all(), [ 'name' => 'required', 'email' => 'required|email|unique:users', 'password' => 'required|confirmed|min:8', ]); if($validator->fails()){ return response()->json($validator->errors()->toJson(), 400); } $user = new User; $user->name = request()->name; $user->email = request()->email; $user->password = bcrypt(request()->password); $user->save(); return response()->json($user, 201); } public function login() { $credentials = request(['email', 'password']); if (! $token = auth('api')->attempt($credentials)) { return response()->json(['error' => 'Unauthorized'], 401); } return $this->respondWithToken($token); } public function me() { return response()->json(auth('api')->user()); } public function logout() { auth('api')->logout(); return response()->json(['message' => 'Successfully logged out']); } public function refresh() { return $this->respondWithToken(JWTAuth::refresh()); } protected function respondWithToken($token) { return response()->json([ 'access_token' => $token, 'token_type' => 'bearer', 'expires_in' => JWTAuth::factory()->getTTL() * 60 ]); } } 10. In routes/api.php, register routes with auth:api middleware to ensure user authentication before processing requests.
routes/api.php
use Illuminate\Support\Facades\Route; use App\Http\Controllers\AuthController; Route::group([ 'middleware' => 'api', 'prefix' => 'auth' ], function ($router) { Route::post('/register', [AuthController::class, 'register'])->name('register'); Route::post('/login', [AuthController::class, 'login'])->name('login'); Route::post('/logout', [AuthController::class, 'logout'])->middleware('auth:api')->name('logout'); Route::post('/refresh', [AuthController::class, 'refresh'])->middleware('auth:api')->name('refresh'); Route::post('/me', [AuthController::class, 'me'])->middleware('auth:api')->name('me'); });